Imports cmplib01
Imports FMPLib01
Imports System.Drawing
Imports System.Drawing.Drawing2D


Public Class cDeploymentManager
    ' this class handles deployment of units and reduction of faction point values.

    ' order of actions:
    ' player selects the deploy option in GUI which calls attemptdeploy
    ' attemptdeploy checks 
    ' the location to an available deploymentzone (including objectives that can deploy)
    '       outside of deploymentzone throws OutOfDeploymentZoneException
    ' the movementclass of the unit/token being deployed vs terrain type
    '       throw InvalidMovementClass exception

    Private c_Module As String = "cDeploymentManager"
    Private ptrCurrentGame As CampaignerGameData
    Private ptrFMP As FlexMapData
    Private ptrLocation As Point
    Private ptrDeploymentZone As DeploymentZone

    Public Function AttemptDeploy(ByRef game As CampaignerGameData, ByRef FMP As FlexMapData, ByVal location As Point) As Boolean
        ' set up pointers
        Dim fact As Faction = game.Faction_g.Item(game.selectedPlayer.FactionKey)
        Dim done As Boolean
        Dim BG As BattlegroupChit '// the group to be deployed. uhuh.
        Dim isOOBUnit As Boolean = False
        Dim BadDeploy As Boolean = False    '// if it can't be deployed.

        Try
            ptrCurrentGame = game
            ptrFMP = FMP
            ptrLocation = location

            SetDeploymentZone(location)

            BG = New BattlegroupChit
            BG.members = New ChitMembers

            Dim f3 As New frmDeployment
            f3.ShowDialog(ptrCurrentGame, ptrDeploymentZone, BG, ptrFMP.MoveTypeLookup)
            isOOBUnit = False
            If f3.DeployCancelled Then Return False

            BG.Location = location
            BG.OwningPlayer = ptrCurrentGame.selectedPlayer
            BG.OwningFaction = fact
            BG.CurrentPV = BG.deployedpointvalue
            BG.order = "Hold"

            '// before adding the unit, we have to make sure the PV of the faction and the PV of the deployment zone can handle it.
            If ptrDeploymentZone.PointsDeployedThisTurn + BG.deployedpointvalue > ptrDeploymentZone.MaxDeploymentPerTurn Then BadDeploy = True
            If ptrDeploymentZone.MaxTotalDeploy < BG.deployedpointvalue Then BadDeploy = True
            If ptrCurrentGame.selectedFaction.FactionTotalPoints < BG.deployedpointvalue Then BadDeploy = True
            '// if its not active
            If ptrDeploymentZone.Active = False Then Return False

            If BadDeploy Then
                MessageBox.Show("You must have enough points remaining in this deployment zone, and in your faction to deploy this unit.", "Not enough points.", MessageBoxButtons.OK)
                Return False
            End If

            '// check to see if we can deploy this unit to the spot selected
            If OKToDeploy(location, BG) = False Then
                Return False
            End If

            '// now we must set the bg point value to the deployedpoint value for all bgs in the bg...
            BG.calculateProperties()  '// we want all the properties for this bad boy set properly.
            SetPointValuesForDeployed(BG)

            '// we should make sure that its a unique name
            ptrCurrentGame.Chits.add(BG)

            '// reduce point values
            ptrDeploymentZone.PointsDeployedThisTurn += BG.deployedpointvalue
            ptrDeploymentZone.MaxTotalDeploy -= BG.deployedpointvalue
            ptrCurrentGame.selectedFaction.FactionTotalDeployedPoints += BG.deployedpointvalue
            '// don't need to reduce the total points!!
            'ptrCurrentGame.selectedFaction.FactionTotalPoints -= BG.deployedpointvalue

            '// if its forced oob then we need to remove the bg from the oob list.
            If isOOBUnit = True Then
                ptrCurrentGame.selectedFaction.OrderOfBattle.remove(BG)
            End If

            BG.Status = GroundUnitStatus_cgd.Assembling
            Return True

        Catch stinker As OutOfDeploymentZoneException
            '// this just means an area outside of a deployment zone was clicked. Yah.
            Return False
        Catch ex As Exception
            HandleException(c_Module, ex)
        End Try

    End Function

    Private Sub SetPointValuesForDeployed(ByRef bg As BattlegroupChit)
        Try
            For Each mem As ChitMember In bg.members
                If mem.UnitType = GroundChitClass_cgd.Battlegroup Then
                    DirectCast(mem, BattlegroupChit).deployedpointvalue = DirectCast(mem, BattlegroupChit).CurrentPV
                End If
            Next

            bg.CurrentPV = bg.SuggestedPointValue
            bg.deployedpointvalue = bg.SuggestedPointValue

        Catch ex As Exception
            HandleException(c_Module, ex)
        End Try
    End Sub

    Public Function AttemptObjectiveDeployment(ByRef game As CampaignerGameData, ByRef FMP As FlexMapData, ByRef inst As InstallationChit) As Boolean
        ' this is used if a user selects the internal rule "Deployment"

    End Function

    Private Function OKToDeploy(ByVal location As Point, ByRef bg As BattlegroupChit) As Boolean
        ' this function determines if the deployed unit would be able to move in the target terrain
        Try
            Dim va As Boolean = ptrFMP.MovementAllowed(location, bg.movementClassID)

            If va = False Then
                Dim terr, snack As String
                ptrFMP.TerrainInfoAtCoord(location, terr, snack)
                MessageBox.Show(bg.Name.ToUpper & " can't be deployed in '" & terr & "'.")
            End If

            Return va

        Catch ex As Exception
            Return False
        End Try
    End Function

    Private Sub SetDeploymentZone(ByVal location As Point)
        ' check each deploymentzone
        '1 turn each deployment zone into a region
        ' check for visibilty on each deployment zone
        ' check point value available for the deployment zone
        Dim key As String
        Dim dep As DeploymentZone
        Dim fac As Faction

        fac = ptrCurrentGame.Faction_g.Item(ptrCurrentGame.selectedPlayer.FactionKey)

        For Each key In ptrCurrentGame.DeploymentZones_g.HT.Keys
            Dim reg As New Region()
            dep = ptrCurrentGame.DeploymentZones_g.Item(key)
            If dep.FactionID = fac.FactionID Then
                ' if there are no available points for this turn, ignore
                If ((dep.MaxDeploymentPerTurn - dep.PointsDeployedThisTurn > 0) And (dep.MaxTotalDeploy > 0)) Then
                    ' it belongs to the current player's faction
                    reg.Intersect(dep.BoundaryGraphicsPath)
                    If reg.IsVisible(location.X, location.Y) Then
                        ' we can exit after we set it up.
                        ptrDeploymentZone = dep
                        Exit Sub
                    End If
                End If
            End If
        Next

        Throw New OutOfDeploymentZoneException()

    End Sub

End Class


' EXCEPTIONS
Public Class OutOfDeploymentZoneException
    Inherits Exception

    Public Shadows Function Message() As String
        Return "The selected point is not within the bounds of any deployment zone."
    End Function
End Class

Public Class InvalidMovementClassException
    Inherits Exception

    Public Shadows Function Message() As String
        Return "The unit is not able to be deployed to the terrain at that coordinate."
    End Function
End Class